home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / smtp / smtpd.2.9.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-11  |  5.4 KB  |  238 lines

  1. /*
  2.  *                      S M T P D A E M O N . C
  3.  *
  4.  *  Server SMTP daemon, for 4.1a/4.2 BSD by DPK at BRL, 1 Jan 82 (Sigh...)
  5.  *
  6.  *              R E V I S I O N   H I S T O R Y
  7.  *
  8.  *      02/02/83  MJM   Modified to be more robust.
  9.  *
  10.  *      03/18/83  DPK   Modified for 4.1c.
  11.  */
  12.  
  13. #include "util.h"
  14. #include <signal.h>
  15. #include <netdb.h>
  16. #include <sys/socket.h>
  17. #include <netinet/in.h>
  18. #include <sys/wait.h>
  19. #include <sys/ioctl.h>
  20.  
  21. extern  int errno;
  22.  
  23. struct sockaddr_in addr;
  24.  
  25. char    *Smtpserver = 0;        /* Actual smtp server process, full path */
  26. char    *Channel = 0;           /* Logical channel mail will arrive on */
  27. int     Maxconnections = 4;     /* Maximum simultaneous connections */
  28. int     numconnections = 0;     /* Number of currently active connections */
  29. int     debug = 0;              /* If nonzero, give verbose output on stderr */
  30. #define    logx    if (debug) log
  31. char    errbuf[BUFSIZ];         /* Logging will be line buffered */
  32. char    programid[40];          /* identification string for log entries */
  33. int     stricked;               /* force full validity of source address */
  34.  
  35. main (argc, argv)
  36. int     argc;
  37. char    **argv;
  38. {
  39.     register int    skt;
  40.     int     pid;
  41.     int     i;
  42.     char    thishost[64];
  43.     char    workarea[32];
  44.     struct  servent *sp;
  45.     struct  hostent *hp;
  46.  
  47.     setbuf( stderr, errbuf );
  48.     sprintf( programid, "smtpdae(%5.5d): ", getpid());
  49.     gethostname( thishost, sizeof(thishost));       /* current hostname */
  50.     if ((sp = getservbyname("smtp", "tcp")) == NULL) {
  51.         fprintf(stderr, "Cannot find service smtp/tcp\n");
  52.         exit(-1);
  53.     }
  54.  
  55.     /*
  56.      * try to check if name is complete.
  57.      */
  58.     if( (hp = gethostbyname(thishost)) != NULL)
  59.         strcpy(thishost, hp->h_name);
  60.  
  61.     /* Parse args; args will override configuration file... */
  62.     arginit( argc, argv );
  63.  
  64.     addr.sin_family = AF_INET;
  65.     addr.sin_addr.s_addr = INADDR_ANY;
  66.     addr.sin_port = (short)sp->s_port;
  67.  
  68.     disconnect ();          /* close off contact with controlling TTY */
  69.  
  70.     while (1)
  71.     {
  72.         struct sockaddr_in rmtaddr;
  73.         int     tmpskt;
  74.         int     status;
  75.  
  76.         /*
  77.          *  Create a socket to accept a SMTP connection on.
  78.          */
  79.  
  80.         logx("opening socket...");
  81.         skt = socket(SOCK_STREAM, 0, &addr, SO_ACCEPTCONN);
  82.         if( skt < 0 ) {
  83.             logx( "can't open socket (errno %d)", errno);
  84.             exit (99);
  85.         }
  86.         logx( "socket open on %d", skt );
  87.         /*
  88.          *  Accept a connection.
  89.          */
  90.         if(accept(skt, &rmtaddr) < 0) {
  91.             logx( "accept error (%d)", errno);
  92.             sleep(1);
  93.             continue;
  94.         }
  95.  
  96.         /* We have a valid open connection, start a server... */
  97.         if(( pid = fork()) < 0 ) {
  98.             logx( "could not fork (%d)", errno);
  99.             close( skt );
  100.         } else if( pid == 0 ) {
  101.             /*
  102.              *  Child
  103.              */
  104.             char    *rmt;
  105.  
  106.             hp = gethostbyaddr(&rmtaddr.sin_addr,
  107.                     sizeof(rmtaddr.sin_addr), AF_INET);
  108.             if((hp == NULL) || !isstr(hp->h_name))
  109.                 rmt = inet_ntoa(rmtaddr.sin_addr);
  110.             else
  111.                 rmt = hp->h_name;
  112.  
  113.             logx( "%s started", rmt);
  114.             dup2( skt, 0 );
  115.             dup2( skt, 1 );
  116.             if( skt > 1 )
  117.                 close( skt );
  118.             execl (Smtpserver, stricked? "rsmtpsrvr" : "smtpsrvr",
  119.                         rmt, thishost, Channel, 0);
  120.             logx( "server exec error (%d)", errno);
  121.             exit (99);
  122.         }
  123.  
  124.         /*
  125.          *  Parent
  126.          */
  127.         close( skt );
  128.         numconnections++;
  129.  
  130.         /*
  131.          *  This code collects ZOMBIES and implements load
  132.          *  limiting by staying in the do loop while the
  133.          *  Maxconnections active.
  134.          */
  135.         while (wait2 (&status, numconnections < Maxconnections
  136.             ? WNOHANG : 0, 0) > 0)
  137.             numconnections--;
  138.     }
  139. }
  140.  
  141. arginit(argc, argv)
  142. int     argc;
  143. char    **argv;
  144. {
  145.     register    int    ch;
  146.     extern        char    *optarg;
  147.     extern        int    optind;
  148.  
  149.     while ((ch = getopt(argc, argv, "dfn:")) != EOF) {
  150.         switch (ch) {
  151.         case 'd':
  152.             debug = TRUE;
  153.             break;
  154.  
  155.         case 'f':       /* force correctness of addresses */
  156.             stricked++;
  157.             break;
  158.  
  159.         case 'n':
  160.             Maxconnections = atoi(optarg);
  161.             if (Maxconnections <= 0) {
  162.                 logx( "Bad number of connections '%s'", optarg);
  163.                 exit( 99 );
  164.             }
  165.             logx( "Maxconnection now %d", Maxconnections );
  166.             break;
  167.  
  168.         default:
  169.             log("Usage: %s [-df] [-n #connections] smtpserver channel", argv[0]);
  170.             exit(1);
  171.             break;
  172.         }
  173.     }
  174.  
  175.     if (optind == argc) {
  176.         log("Usage: %s [-df] [-n #connections] smtpserver channel", argv[0]);
  177.         exit(1);
  178.     }
  179.  
  180.     if (optind < argc) {
  181.         if (access(argv[optind], 01) < 0) {    /* execute privs? */
  182.             logx("Cannot access server program '%s'", argv[optind]);
  183.             exit(99);
  184.         }
  185.         Smtpserver = argv[optind];
  186.         logx("server is '%s'", Smtpserver);
  187.     } else {
  188.         logx("Smtpserver program not specified!");
  189.         exit(99);
  190.     }
  191.  
  192.     if (++optind < argc) {
  193.         Channel = argv[optind];
  194.         logx("channel is '%s'", Channel);
  195.     } else {
  196.         logx("Channel not specified!");
  197.         exit(99);
  198.     }
  199. }
  200.  
  201. /* VARARGS */
  202. log( fmt, a, b, c, d )
  203. char *fmt;
  204. {
  205.     fputs( programid, stderr );
  206.     fprintf( stderr, fmt, a, b, c, d );
  207.     fputc( '\n', stderr );
  208.     fflush( stderr );
  209. }
  210. /*
  211. **  DISCONNECT -- remove our connection with any foreground process
  212. **
  213. **      Parameters:
  214. **              fulldrop -- if set, we should also drop the controlling
  215. **                      TTY if possible -- this should only be done when
  216. **                      setting up the daemon since otherwise UUCP can
  217. **                      leave us trying to open a dialin, and we will
  218. **                      wait for the carrier.
  219. **
  220. **      Returns:
  221. **              none
  222. **
  223. **      Side Effects:
  224. **              Trys to insure that we are immune to vagaries of
  225. **              the controlling tty.
  226. */
  227.  
  228. disconnect ()
  229. {
  230.     int fd;
  231.  
  232.     if( (fd = open("/dev/tty", 2)) >= 0){
  233.         (void) ioctl(fd, TIOCNOTTY, 0);
  234.         (void) close(fd);
  235.     }
  236.     errno = 0;
  237. }
  238.